赞
踩
1)pom.xml文件添加依赖
<!-- spring security依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2)User类,实现了UserDetails
@lombok.Data public class User implements UserDetails { private int id; private String username; private String account; private String password; private String email; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date createDate; private boolean isLockedOut; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date lastLoginDate; private int incorrectLoginAttempt; private String realname; private String empId; private int roleId; private boolean isHintEnabled; private List<GrantedAuthority> authorities = new ArrayList<>(); @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
3)UserMapper接口
@Mapper
public interface UserMapper extends BaseMapper<User> {
public User findUserByUsername(String account);
public User findUserByUsernameAndPassword(String account, String password);
/**查询当前用户拥有的权限*/
public List<Permission> findPermissionByUsername(String account);
public List<User> findAllMembersOfCorporation(Integer corporationId);
public boolean insertOfReturnId(User user);
}
4)Mybatis的xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.taobao.rigel.rap.mapper.UserMapper"> <resultMap id="UserMap" type="com.taobao.rigel.rap.model.User"> <id column="id" property="id"/> <result column="name" property="username"/> <result column="account" property="account"/> <result column="password" property="password"/> <result column="email" property="email"/> <result column="create_date" property="createDate"/> <result column="is_locked_out" property="isLockedOut"/> <result column="last_login_date" property="lastLoginDate"/> <result column="incorrect_login_attempt" property="incorrectLoginAttempt"/> <result column="realname" property="realname"/> <result column="emp_id" property="empId"/> <result column="is_hint_enabled" property="isHintEnabled"/> </resultMap> <select id="findUserByUsername" parameterType="java.lang.String" resultMap="UserMap"> select u.* , r.role from tb_user_new u left join tb_role_and_user_new ur on u.id = ur.user_id left join tb_role_new r on ur.role_id = r.id where u.account=#{account} </select> <select id="findPermissionByUsername" parameterType="String" resultType="com.taobao.rigel.rap.model.Permission"> SELECT permission.* FROM tb_user_new user INNER JOIN tb_role_and_user_new user_role ON user.id = user_role.user_id INNER JOIN tb_permission_and_role_new role_permission ON user_role.role_id = role_permission.role_id INNER JOIN tb_permission_new permission ON role_permission.permission_id = permission.id WHERE user.account=#{account}; </select> <select id="findAllMembersOfCorporation" parameterType="java.lang.Integer" resultMap="UserMap"> select u.* from tb_user_new u INNER JOIN tb_corporation_and_user_new cu on u.id = cu.user_id where cu.corporation_id=#{corporationId} </select> <update id="update" parameterType="com.taobao.rigel.rap.model.User"> update tb_user_new set name=#{username}, account=#{account}, password=#{password}, email=#{email}, last_login_date=#{lastLoginDate} where id=#{id} </update> <insert id="insertOfReturnId" parameterType="com.taobao.rigel.rap.model.User" useGeneratedKeys="true" keyProperty="id"> insert into tb_user_new (name, account, password, email, create_date, last_login_date) values (#{username}, #{account}, #{password}, #{email}, #{createDate}, #{lastLoginDate}) <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> select LAST_INSERT_ID() </selectKey> </insert> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> delete from tb_user_new where id=#{id} </delete> </mapper>
5)自定义UserDetailsService接口的实现类
@Service public class MyUserDetailService implements UserDetailsService { Logger logger = LoggerFactory.getLogger(getClass()); @Autowired UserMapper userMapper; @Override public UserDetails loadUserByUsername(String account) throws UsernameNotFoundException { System.out.println("loadUserByUsername"); //根据用户名查询用户信息 User user = userMapper.findUserByUsername(account); System.out.println("从数据库中查询出的用户信息:" + user); if(user != null){ //根据用户名查询当前用户所有权限 List<Permission> permissionList = userMapper.findPermissionByUsername(account); //authorities: 存放所有用户权限 List<GrantedAuthority> authorities = new ArrayList<>(); for(Permission permission : permissionList){ GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getPermission()); authorities.add(grantedAuthority); } //把所有权限赋值给user user.setAuthorities(authorities); logger.info("当前用户为: "+user); }else{ System.out.println("用户不存在"); // throw new UsernameNotFoundException("用户不存在!"); } return user; } }
6)自定义WebSecurityConfigurerAdapter的配置类
@EnableWebSecurity public class MySecurityConfig extends WebSecurityConfigurerAdapter { Logger logger = LoggerFactory.getLogger(getClass()); @Autowired MyUserDetailService myUserDetailService; //Control+O 打开重写方法 //定制请求的授权规则 @Override protected void configure(HttpSecurity http) throws Exception { System.out.println("进入到 MySecurityConfig的configure 方法中"); //super.configure(http); /*Spring Security 的默认构造器: 通过调用authorizeRequests()和 anyRequest().authenticated()就会要求所有进入应用的HTTP请求都要进行认证 http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin().and() .httpBasic(); //弹出一个输入用户名、密码的登录框 “/shop/hello” 和 “/shop/order” 这两个路径必须进过认证,并且 “/shop/order” 必须是 post 请求的方式. 对于其他的请求,我们都是 .anyRequest().permitAll() ;都放行. http.authorizeRequests() .antMatchers("/shop/hello").authenticated() .antMatchers(HttpMethod.POST,"/shop/order").authenticated() .anyRequest().permitAll(); antMatchers()方法所使用的路径可能会包括Ant风格的通配符,而regexMatchers()方法则能够接受正则表达式来定义请求路径。 */ // 基于token,所以不需要session http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // /**代表所有的请求 http.authorizeRequests()//方法表示开启了认证规则配置;定义哪些url需要保护,哪些url不需要保护; .antMatchers("/api/**").permitAll()//定义不需要认证就可以访问 // .antMatchers("/session/**").permitAll()//定义不需要认证就可以访问 // .antMatchers("/component/**").hasAuthority("ROLE_ADMIN") .antMatchers("/home/**").hasAnyAuthority("ROLE_DEV_APPLICATION","ROLE_ADMIN","ROLE_DEV_TERMINAL_IOS") .anyRequest().authenticated();其他的路径都是登录后即可访问 // .and().formLogin().loginPage("/") // // //在successHandler中,使用response返回登录成功的json即可,切记不可以使用defaultSuccessUrl,defaultSuccessUrl是只登录成功后重定向的页面,failureHandler也是由于相同的原因不使用failureUrl。 // .loginProcessingUrl("/login").successHandler( // new AuthenticationSuccessHandler(){ // @Override // public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { // System.out.println(authentication.getDetails()); // httpServletResponse.setContentType("application/json;charset=utf-8"); // PrintWriter out = httpServletResponse.getWriter(); // out.write("{\"status\":\"success\",\"msg\":\"登录成功\"}"); // out.flush(); // out.close(); // } // }).failureHandler( // new AuthenticationFailureHandler() { // @Override // public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { // httpServletResponse.setContentType("application/json;charset=utf-8"); // PrintWriter out = httpServletResponse.getWriter(); // out.write("{\"status\":\"failed\",\"msg\":\"登录失败\"}"); // out.flush(); // out.close(); // } // }); //http.logout()开启自动配置的注销功能 //1) 访问/logout 表示用户注销,清空session //2) 注销成功会返回/login?logout 页面 //3) logoutSuccessfulUrl 改变2)的设置 http.logout().logoutSuccessUrl("/login"); http.sessionManagement().invalidSessionUrl("/login"); http.rememberMe().rememberMeParameter("remember"); // .usernameParameter("username").passwordParameter("password").defaultSuccessUrl("/");定义当需要用户登录时候,转到的登录页面 // http.headers().frameOptions().disable(); // .antMatchers("/level2/**").hasRole("VIP2") // .antMatchers("/level3/**").hasRole("VIP3"); //开启自动配置的登录功能。如果没有登录,没有权限就会来到登录页面 //1:/login来到登录页 //2:重定向/login?error表示登录失败 //3:更多详细规定 //http.formLogin().defaultSuccessUrl("/user/login.html"); /* iframe */ http.headers().frameOptions().sameOrigin(); // 运行同一个域名中的任何请求 http.csrf().disable(); // 默认是启用的,需要禁用CSRF保护(当不使用cookie时可以禁用csrf) http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); // 禁用缓存 http.headers().cacheControl(); } //定制请求的认证规则 @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { System.out.println("进入到 configureGlobal 方法中"); System.out.println("auth.userDetailsService(myUserDetailService):" + auth.userDetailsService(myUserDetailService)); //1)获取内存中的用户名和密码 // auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("1").password(new BCryptPasswordEncoder().encode("1")).roles("USER"); // .withUser("1").password(new BCryptPasswordEncoder().encode("1")).authorities("ROLE_TEST"); // auth.authenticationProvider(authenticationProvider()); // auth.userDetailsService(myUserDetailService).passwordEncoder(passwordEncoder()); //2)获取数据库中的用户名和密码 auth.userDetailsService(myUserDetailService).passwordEncoder(new PasswordEncoder() { @Override public String encode(CharSequence charSequence) { return charSequence.toString(); } @Override public boolean matches(CharSequence charSequence, String s) { return s.equals(charSequence.toString()); } }); } /* 通过AuthenticationProvider方式获取 */ @Bean public DaoAuthenticationProvider authenticationProvider() { System.out.println("进入到 authenticationProvider 方法中"); DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); authProvider.setUserDetailsService(myUserDetailService); authProvider.setPasswordEncoder(passwordEncoder()); return authProvider; } /** * 密码生成策略 * @return */ @Bean public BCryptPasswordEncoder passwordEncoder() { System.out.println("进入到 passwordEncoder 方法中"); return new BCryptPasswordEncoder(); } @Bean public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception { System.out.println("进入到 authenticationTokenFilterBean 方法中"); return new JwtAuthenticationTokenFilter(); } }
7)LoginController
@RestController @RequestMapping(value = "api/umeapiplus/login") public class LoginController { @Autowired MyUserDetailService myUserDetailService; @Autowired JwtTokenUtils jwtTokenUtils; @Autowired BCryptPasswordEncoder bCryptPasswordEncoder; @RequestMapping(value = "/login", method = RequestMethod.POST) public Map<String, Object> login(@RequestBody JSONObject requestParam){ System.out.println("前端传递过来的登陆信息参数:" + JSONObject.toJSONString(requestParam)); Map<String, Object> returnMap = new HashMap<>(); String account = requestParam.getString("account"); String password = requestParam.getString("password"); User user = (User) myUserDetailService.loadUserByUsername(account); System.out.println("返回的用户信息:" + user); if(user == null){ System.out.println("账号不存在"); returnMap.put("code", 400); returnMap.put("msg", "账号不存在"); returnMap.put("data", null); returnMap.put("token", null); }else { // 正常应该是从user.getPassword()得到数据库中的加密密码 String encodedPassword = bCryptPasswordEncoder.encode(password); System.out.println("原始密码:" + password + " bcr加密后的密码:" + encodedPassword); boolean compareRes = bCryptPasswordEncoder.matches(password, encodedPassword); System.out.println("compareRes: " + compareRes); if(!compareRes){ System.out.println("密码错误"); returnMap.put("code", 400); returnMap.put("msg", "密码错误"); returnMap.put("data", null); returnMap.put("token", null); }else { String token = jwtTokenUtils.generateToken(user); System.out.println("根据用户名和密码生成的token信息:" + token); returnMap.put("code", 200); returnMap.put("msg", "登录成功"); returnMap.put("data", user); returnMap.put("token", token); } } return returnMap; } }
1)main.js
import Vue from 'vue' import Antd from 'ant-design-vue' import 'ant-design-vue/dist/antd.css' import axios from 'axios' Vue.prototype.axios = axios import store from './store' import router from './router' import App from './App.vue' import './css/style.css' Vue.use(Antd); Vue.config.productionTip = false router.beforeEach((to, from, next) => { console.log('to.path: ' + to.path); if (to.path === '/') { next(); } else { if (window.sessionStorage.getItem("user")) { next(); } } }) new Vue({ store, router, render: h => h(App), }).$mount('#app')
2)vue-router的index.js
import Vue from 'vue' import Router from 'vue-router' import Login from '../components/login/Login.vue' import HomePage from '../components/New/HomePage.vue' Vue.use(Router) export default new Router({ base: '/dist/', //添加的地方 routes: [ { path: '/', name: 'Login', component: Login, hidden: true }, { path: '/home', name: 'Home', component: HomePage, hidden: true, meta: { roles: ['admin', 'user'] } }, { path: '*', redirect: '/home' } ] })
3)Login.vue
<template> <div> <a-form :rules="rules" :form="form" ref="loginForm" :model="loginForm" @submit="submitLogin" class="loginContainer"> <h3 class="loginTitle">系统登录</h3> <span style="font-size: 8px;color: #13c2c2">用户名为邮箱前缀,密码为123456</span> <a-form-item label="用户名"> <a-input type="text" v-model="loginForm.account" auto-complete="off" placeholder="请输入用户名"></a-input> </a-form-item> <a-form-item label="密码"> <a-input type="password" v-model="loginForm.password" auto-complete="off" placeholder="请输入密码"></a-input> </a-form-item> <a-form-item :wrapper-col="{ span: 12, offset: 5 }"> <a-button type="primary" html-type="submit"> 登录 </a-button> </a-form-item> </a-form> </div> </template> <script> import {login} from '../../utils/api' export default { name: "Login", data() { return { loading: false, loginForm: { account: '', password: '' }, checked: true, rules: { account: [{required: true, message: '请输入用户名', trigger: 'blur'}], password: [{required: true, message: '请输入密码', trigger: 'blur'}], } } }, beforeCreate() { this.form = this.$form.createForm(this, {name: 'validate_other'}) }, methods: { submitLogin(e) { e.preventDefault(); this.form.validateFields((err, values) => { if (!err) { console.log('Received values of form: ', values); this.loading = true; console.log('this.loginForm: ' + JSON.stringify(this.loginForm)) login(this.loginForm).then((res) => { this.loading = false; console.log('登录的返回结果:' + JSON.stringify(res.data)) this.$message.info(res.data.msg) if (res.data.code === 200) { this.$store.commit('editCurrentUser', res.data.data); window.sessionStorage.setItem('user', JSON.stringify(res.data.data)); this.$router.push('home').catch(err => { console.log('all good ' + err) }) } }) } else { return false; } }); } } } </script> <style> .loginContainer { border-radius: 15px; background-clip: padding-box; margin: 180px auto; width: 350px; padding: 15px 35px 15px 35px; background: #fff; border: 1px solid #eaeaea; box-shadow: 0 0 25px #cac6c6; } .loginTitle { margin: 15px auto 20px auto; text-align: center; color: #505458; } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。