In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This "springboot how to integrate shiro to achieve multi-authentication login function" article knowledge points most people do not understand, so the editor summarized the following content, detailed, clear steps, with a certain reference value, I hope you can get something after reading this article, let's take a look at this "springboot how to integrate shiro to achieve multi-authentication login function" article.
1. First, create a new configuration class for shiroConfig shiro, as follows:
@ Configurationpublic class SpringShiroConfig {/ * @ param realms uses the interface collection here to implement * @ return * / @ Bean public SecurityManager securityManager (Collection realms) {DefaultWebSecurityManager sManager = new DefaultWebSecurityManager (); sManager.setRealms (realms); return sManager;} @ Bean public ShiroFilterFactoryBean shiroFilterFactory (SecurityManager securityManager) {ShiroFilterFactoryBean sfBean = new ShiroFilterFactoryBean () SfBean.setSecurityManager (securityManager); / / in the case of anonymous access, sfBean.setLoginUrl ("/ index") where resources that cannot be accessed are accessed; / / define map to specify request filtering rules (which resources allow anonymous access and which must authenticate access) LinkedHashMap map = new LinkedHashMap () / / static resources allow anonymous access: "anon" static resources cannot be authorized to write all the opening under static. To open all folders under static one by one, the key of templates / / map can be either the location of the file or the requested path map.put ("/ bower_components/**", "anon"). Map.put ("/ json/**", "anon"); map.put ("/ pages", "anon"); map.put ("/ user/userPasswordLogin", "anon"); map.put ("/ user/login", "anon"); map.put ("/ user/reg", "anon") / / access to this path will not enter controller, but will directly block and exit here. Ask why, you want to request the process to go to map.put ("/ user/userLogout", "logout"); / / block all request paths except the above map.put ("/ * *", "user"); sfBean.setFilterChainDefinitionMap (map); return sfBean @ Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor () {return new LifecycleBeanPostProcessor ();}
two。 Write the implementation class of Realms, which is generally inherited from AuthorizingRealm (this is the implementation user name, password login). The code is as follows:
@ Servicepublic class ShioUserRealm extends AuthorizingRealm {/ / inject userdao @ Autowired private UserDao userDao; / * set credential matcher * * @ param credentialsMatcher * / @ Override public void setCredentialsMatcher (CredentialsMatcher credentialsMatcher) {/ * if MD5 salt encryption is set here, you must use HashedCredentialsMatcher to have the following two methods * / HashedCredentialsMatcher matcher = new HashedCredentialsMatcher () / / here is to set the encryption mode matcher.setHashAlgorithmName ("MD5"); / / here is to set the number of times of encryption matcher.setHashIterations (2); super.setCredentialsMatcher (matcher);} / * here is to set the authorization * @ param principalCollection * @ return * / @ Override protected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principalCollection) {return null } / * complete the acquisition and encapsulation of authentication data through this method, and the bottom layer of the system will transfer the authentication data to the authentication manager. The authentication manager completes the authentication operation * @ param authenticationToken * @ return * @ throws AuthenticationException * / @ Override protected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken authenticationToken) throws AuthenticationException {/ / first determines whether this comes from the data of this token: we are divided into UsernamePasswordToken (provided to us by shiro). ), UserPhoneToken if (! (authenticationToken instanceof UsernamePasswordToken)) {return null;} / / get the data sent by controller UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken; / / upToken.setRememberMe (true); Shirodefault is false, whether to remember my function / / username String username = upToken.getUsername () submitted here for the user / / more name to get the user's information User user = userDao.findUserByUserName (username); / / to determine whether the database has the user if (user = = null) {throw new UnknownAccountException () } / / determine whether the user's status is disabled (database field) if (user.getState () = = 0) {throw new LockedAccountException ();} / / here is the salt value taken from the user's information, and the salt value must be converted to ByteSource before ByteSource credentialsSalt = ByteSource.Util.bytes (user.getSalt ()) can be used. / / here is to give the user's information to shiro (user is the user object, user.getPassword () is the object to be encrypted, credentialsSalt is salt, getName () current object) SimpleAuthenticationInfo info = new SimpleAuthenticationInfo (user, user.getPassword (), credentialsSalt, getName ()); return info;}}
3. At this point, the user's account password can be logged in with the controller code as follows:
RequestMapping ("userPasswordLogin") @ ResponseBody public JsonResult userPasswordLogin (String username, String password) {Subject subject = SecurityUtils.getSubject (); UsernamePasswordToken token = new UsernamePasswordToken (username, password); subject.login (token); return new JsonResult ("login Ok");}
4. Now let's implement the login implementation of SMS verification code:
Write UserPhoneToken first, and I put it in the same directory as l and springShiroConfig:
@ Componentpublic class UserPhoneToken extends UsernamePasswordToken implements Serializable {private static final long serialVersionUID = 6293390033867929958L; / / Mobile number private String phoneNum; / / No-parameter construction public UserPhoneToken () {} / / get the stored value @ Override public Object getPrincipal () {if (phoneNum = = null) {return getUsername ();} else {return getPhoneNum () } @ Override public Object getCredentials () {if (phoneNum = = null) {return getPassword ();} else {return "ok";}} public UserPhoneToken (String phoneNum) {this.phoneNum = phoneNum;} public UserPhoneToken (final String userName, final String password) {super (userName, password) } public String getPhoneNum () {return phoneNum;} public void setPhoneNum (String phoneNum) {this.phoneNum = phoneNum;} @ Override public String toString () {return "PhoneToken [PhoneNum=" + phoneNum + "]";}}
4.2 while writing shiroUserPhoneRealm, the code is as follows:
@ Servicepublic class ShioUserPhoneRealm extends AuthorizingRealm {@ Autowired private UserDao userDao; @ Override public void setCredentialsMatcher (CredentialsMatcher credentialsMatcher) {/ / the new object of CredentialsMatcher here must be AllowAllCredentialsMatcher CredentialsMatcher matcher = new AllowAllCredentialsMatcher (); super.setCredentialsMatcher (matcher);} @ Override protected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principalCollection) {return null } / * the authentication data is obtained and encapsulated by this method. The bottom layer of the system will transfer the authentication data to the authentication manager, and the authentication manager completes the authentication operation * @ param authenticationToken * @ return * @ throws AuthenticationException * / @ Override protected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken authenticationToken) throws AuthenticationException {UserPhoneToken token = null. If (authenticationToken instanceof UserPhoneToken) {token = (UserPhoneToken) authenticationToken;} else {return null;} / / get the verification code that I sent into session and the mobile number String verificationCode = (String) SecurityUtils.getSubject (). GetSession (). GetAttribute ("verificationCode"); String phone = (String) SecurityUtils.getSubject (). GetSession (). GetAttribute ("phone") / / get the data sent by controller String verificationCode1 = (String) token.getPrincipal (); / / go to the database to query user information based on mobile phone number User user = userDao.findUserByUserPhone (phone); if (StringUtils.isEmpty (verificationCode)) {throw new ServiceException ("network error") } / / compare the mobile number if (! verificationCode.equals (verificationCode1)) {throw new ServiceException ("incorrect verification code");} if (user = = null) {throw new UnknownAccountException ();} if (user.getState () = = 0) {throw new LockedAccountException () } return new SimpleAuthenticationInfo (user,phone,getName ());}
4.3 Login verification of mobile phone number has been basically completed: the controller code is as follows:
@ PostMapping ("verificationCodeLogin") @ ResponseBody public JsonResult verificationCodeLogin (String password) {Subject subject = SecurityUtils.getSubject (); UserPhoneToken token = new UserPhoneToken (password); subject.login (token); return new JsonResult ("login OK");}
Bug encountered during use
1.
Org.apache.shiro.authc.UnknownAccountException: Realm [cn.tedu.wxacs.service.impl.ShioUserPhoneRealm@768d8431] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken-Zhang San, rememberMe=false].
The reason for this problem is that one of the implementation classes in Realm is not annotated. When I demonstrate here, I should add @ Service to ShiroUserRealm.
two。
Org.apache.shiro.authc.AuthenticationException: Authentication token of type [class org.apache.shiro.authc.UsernamePasswordToken] could not be authenticated by any configured realms. Please ensure that at least one realm can authenticate these tokens.
The problem here is that it should be User user = userDao.findUserByUserName (username) of my ShioUserRealm's AuthenticationInfo method; if there is a problem with this line of code, debug will find that this sentence protects the error after execution.
Reason: because the path of the mapper file corresponding to dao is not written in my application.yml file
3. The error is reported after the new SimpleAuthenticationInfo (user,phone,getName ()) of ShioUserPhoneRealm's doGetAuthenticationInfo method is due to ShioUserPhoneRealm. In this method, you do not set the object of new to AllowAllCredentialsMatcher ().
@ Override public void setCredentialsMatcher (CredentialsMatcher credentialsMatcher) {/ / the object of CredentialsMatcher's new here must be AllowAllCredentialsMatcher CredentialsMatcher matcher = new AllowAllCredentialsMatcher (); super.setCredentialsMatcher (matcher) } the above is about the content of this article on "how springboot integrates shiro to achieve multi-authentication login function". I believe everyone has a certain understanding. I hope the content shared by the editor will be helpful to you. If you want to learn more about related knowledge, please follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.