博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringSecurity+Vue实现前后端分离的认证授权
阅读量:4094 次
发布时间:2019-05-25

本文共 14532 字,大约阅读时间需要 48 分钟。

一、SpringSecurity的配置

1)pom.xml文件添加依赖

org.springframework.boot
spring-boot-starter-security

2)User类,实现了UserDetails

@lombok.Datapublic 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
authorities = new ArrayList<>(); @Override public Collection
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接口

@Mapperpublic interface UserMapper extends BaseMapper
{ public User findUserByUsername(String account); public User findUserByUsernameAndPassword(String account, String password); /**查询当前用户拥有的权限*/ public List
findPermissionByUsername(String account); public List
findAllMembersOfCorporation(Integer corporationId); public boolean insertOfReturnId(User user);}

4)Mybatis的xml文件

update tb_user_new set name=#{username}, account=#{account}, password=#{password}, email=#{email}, last_login_date=#{lastLoginDate} where id=#{id}
insert into tb_user_new (name, account, password, email, create_date, last_login_date) values (#{username}, #{account}, #{password}, #{email}, #{createDate}, #{lastLoginDate})
select LAST_INSERT_ID()
delete from tb_user_new where id=#{id}

5)自定义UserDetailsService接口的实现类

@Servicepublic 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
permissionList = userMapper.findPermissionByUsername(account); //authorities: 存放所有用户权限 List
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的配置类

@EnableWebSecuritypublic 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
login(@RequestBody JSONObject requestParam){ System.out.println("前端传递过来的登陆信息参数:" + JSONObject.toJSONString(requestParam)); Map
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; }}

二、Vue项目代码

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 = axiosimport store from './store'import router from './router'import App from './App.vue'import './css/style.css'Vue.use(Antd);Vue.config.productionTip = falserouter.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

转载地址:http://getii.baihongyu.com/

你可能感兴趣的文章
React Native之原理浅析
查看>>
Git操作清单
查看>>
基础算法
查看>>
前端面试
查看>>
React Hooks 完全指南
查看>>
nvm 和 nrm 的安装与使用
查看>>
Flutter Boost的router管理
查看>>
Android Flutter混合编译
查看>>
微信小程序 Audio API
查看>>
[React Native]react-native-scrollable-tab-view(进阶篇)
查看>>
Vue全家桶+Mint-Ui打造高仿QQMusic,搭配详细说明
查看>>
React Native应用部署/热更新-CodePush最新集成总结(新)
查看>>
react-native-wechat
查看>>
基于云信的react-native聊天系统
查看>>
网易云音乐移动客户端Vue.js
查看>>
ES7 await/async
查看>>
ES7的Async/Await
查看>>
React Native WebView组件实现的BarCode(条形码)、(QRCode)二维码
查看>>
每个人都能做的网易云音乐[vue全家桶]
查看>>
Immutable.js 以及在 react+redux 项目中的实践
查看>>